/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "gui_io.h"
#include "gui_al.h"
#include "error.h"
#include "xml.h"
#include "io.h"
#include "simple.h"
#include "crypt.h"
#include "settings.h"
#include "plugins.h"
#include "login.h"
#include "journal.h"


int sync_needed = 0;
int _lock = 0;

char *_day = NULL;
char *_term = NULL;
	
int *elog_gui_io_res_list = NULL;
int elog_gui_io_res_list_len = 0;
int elog_gui_io_res_cur = -1;

int elog_gui_io_lock_open = 0;

int elog_gui_io_day_list_mode = 0; //0 means show all
                                   //1 means show search results.

int elog_gui_io_lock()
{
	return _lock;
}
	
int _cal_mode = 0;

int elog_gui_io_open(const char *fileName,  struct cal_date *date)
{
  if (elog_gui_io_lock_open)
    return 0;
  elog_gui_io_lock_open = 1;
  const char *journ = elog_journ_in_current(fileName);
  if (journ)
    {
      elog_gui_io_lock_open = 0;
      char *msg;
      elog_sp_cat(&msg, "Switch journal....\nTo: ", journ, "\nFrom: ", elog_journ_current()->name, "\nSo that you can open the entry requested?", NULL);
      int res = elog_wrn_ask(msg, ELOG_WRN_ASK_YESNO);
      free(msg);
      if (res)
	{
	  if (elog_journ_load(journ))
	    {
	      elog_err_print("Failed to load journal!");
	      return 0;
	    }
	}
      else
	return 0;
      elog_gui_io_lock_open = 1;
    }
	
	
  _lock = 1;
  if (sync_needed == 1)
    if (elog_gui_io_save() != 0)
      elog_err_print("Failed to save current entry!\n");
   
   
   
  sync_needed = 0;
  struct elog_xml_doc *current = elog_xml_open(fileName, 1);

   
  if (current != NULL)
    {
      if (current->file_info->encType)
	{
	  if (current->file_info->encType[0] != elog_journ_current()->settings->encryption[0] &&
	      current->file_info->encType[0] == 'A')
	    {
	      if (create_login_window(ELOG_LGN_MODE_RECOVER))
		return 0;
	      else
		{
		  elog_set_set_str("encryption_method", "AES");
		  if (elog_journ_current()->settings->encryption)
		    free(elog_journ_current()->settings->encryption);
		  elog_sp_cat(&(elog_journ_current()->settings->encryption), "AES", NULL);
		}
	    }
	  else if (current->file_info->encType[0] == 'A' &&
	      !viewKey())
	    if (create_login_window(ELOG_LGN_MODE_RECOVER))
	      return 0;
	  //If, the file is for encryption and the journal
	  //isn't then we'll make this an encrypted journal.
	  //If the file is encrypted and there's no key
	  //We'll generate one.

	}
      if (current->year == 0 && current->day == 0) //no date
	{
	  if (!date)
	    {			
	      char *realDay; //taking off the /day at the end, this gives
	      //compatibility with full filenames.
	      char *t;
	      elog_sp_cat(&t, fileName, NULL);
	      *(strrchr(t, '/')) = '\0';
	       
	      elog_sp_cat(&realDay, t, NULL);
	      free(t);
	       
	       
	      struct cal_date *date1 = elog_gui_io_getDate(realDay);
	      free(realDay);
	      current->month = date1->month;
	      current->year = date1->year;
	      current->day = date1->day;
	      free(date1);
	    }
	  else
	    {
	      current->month = date->month;
	      current->year = date->year;
	      current->day = date->day;
	    }
	}
       
       
       
      unsigned int len;
      unsigned char *doc1 = elog_io_readRestofFile(current->handle, &len);
      doc1[len] = '\0';
      elog_io_close(current->handle);



      if (current->file_info->encType == NULL) //doc didn't have enc setting, look global
	{
	  if (elog_set_get_str("encryption_method")[0] == 'A')
	    decryptText(doc1, len);
	}
      else if (current->file_info->encType[0] == 'A')
	decryptText(doc1, len);
       
      char *doc = elog_sp_toChar(doc1, len);
		
      /*Calling plugins*/
      struct elog_plgn_data_io *plgn = malloc(sizeof *plgn);
      plgn->doc = current;
      current->text = doc;
      plgn->xml = current->xml;
      elog_plgn_eff_call_all(ELOG_PLGN_SYM_OPEN, plgn);
      free(plgn);
      /*end plugins*/

       
      elog_gui_previewPane_set(current);

      elog_gui_al_text(doc);
      elog_gui_al_setImage(current->mood, current->weather);
      free(doc);
      int c;
      if (current->links != NULL)
	for (c=0; current->links[c] != NULL; ++c)
	  current->links[c]->num = elog_gui_al_textLink(current->links[c]->start , current->links[c]->end, current->links[c]->href);
       

      elog_gui_io_highlight_do();
       
      elog_gui_io_dispLocation(fileName);
       

      elog_gui_al_page(ELOG_GUI_AL_PAGE_EDIT);

    }
  else
    {
      current = elog_xml_doc_new();
      elog_sp_cat(&(current->fileName), fileName, NULL);

      elog_sp_cat(&(current->created), elog_io_date(), NULL);


      elog_gui_al_lastEdit("Never");
      elog_gui_al_text("");
      elog_gui_al_title("");
      if (!date)
	{		
	  char *realDay; //taking off the /day at the end, this gives
	  //compatibility with full filenames.
	  char *t;
	  elog_sp_cat(&t, fileName, NULL);
	  *(strrchr(t, '/')) = '\0';
	   
	  elog_sp_cat(&realDay, t, NULL);
	  free(t);
	   
	   
	  struct cal_date *date1 = elog_gui_io_getDate(realDay);
	  free(realDay);
	  current->month = date1->month;
	  current->year = date1->year;
	  current->day = date1->day;
	  free(date1);
	}
      else
	{
	  current->month = date->month;
	  current->year = date->year;
	  current->day = date->day;			
	}
      char *day, *month, *year;
      day = elog_sp_shortToString(current->day);
      month = (char *)elog_mnth_str(current->month);
       
      year = elog_sp_shortToString(current->year);
      char *str;
      elog_sp_cat(&str, "The ", day, elog_mnth_day(current->day), " of ", month, ", ", year, NULL);
      elog_gui_al_creationDate(str);
      free(str);
      free(day);
      //elog_gui_al_unlock();
    }
  elog_set_currentFile(current->fileName, &current);
  elog_gui_io_clearUndo();
  elog_gui_io_clearRedo(); //clearing undo/redo buffers.
  _lock = 0;
  elog_gui_io_lock_open = 0;
  return 1;
}
void elog_gui_io_highlight_term(const char *term)
{
	if (_term != NULL)
		free(_term);
	 
	if (term == NULL)
	{
		_term = NULL;
		return;
	}
	elog_sp_cat(&_term, term, NULL);	 
}
 void elog_gui_io_highlight_do()
{
	if (_term == NULL)
		return;
	else if (strlen(_term) < 2)
		return;
	//elog_gui_al_lock();
	elog_gui_al_setVisible(0); //invisible
	elog_gui_al_clearTextMarks(); 
	 
	char *txt = elog_gui_al_text(NULL);
	if (strlen(txt) < 2)
	{
		elog_gui_al_setVisible(1); //visible
		 //elog_gui_al_unlock();
		return;
	}
	int *list = elog_srch_listResults(txt, _term);
	int c;
	for (c=0; list[c] != -1; c+=2)
		elog_gui_al_markText(list[c], list[c+1]);

	elog_gui_io_res_list_len = c;
	if (elog_gui_io_res_list)
		free(elog_gui_io_res_list);
	elog_gui_io_res_list = list;
	elog_gui_io_res_cur = 0;

	elog_gui_al_setVisible(1); //visible
	free(txt);
	 //elog_gui_al_unlock();
}
void elog_gui_io_search(void *in)
{
  struct elog_srch_result *res = (struct elog_srch_result *)in;
  elog_gui_al_lock();
  elog_gui_al_addResult(res);
  elog_gui_al_unlock();
  
  char *fileName = NULL;
  char *f = strrchr(res->fileName, '/');
  if (f)
    {
      elog_sp_cat(&fileName, &(f[1]), NULL);
      fileName[strlen(fileName) - 4] = '\0';
    }
  else
    fileName = res->fileName;


  if (fileName)
    {
      int day = elog_sp_stringToShort(fileName);

      //grabbing the number:  .../1.dry, grab 1
      free(fileName);
      elog_gui_io_view_add_result(res->year, res->month, res->day, day);
    }
  else
    elog_err_print_console("For some reason, res->fileName was undefined?\n");
     
}
 void elog_gui_io_fileHandler(char *fileHandle)
{
	elog_gui_io_save(); //saves current entry before handling link
	 
	if (fileHandle[0] == 'l' && 
		   fileHandle[1] == 'o' &&
		   fileHandle[2] == 'c' &&
		   fileHandle[3] == 'a' &&
		   fileHandle[4] == 'l' &&
		   fileHandle[5] == ':' &&
		   fileHandle[6] == '/' &&
		   fileHandle[7] == '/')
	{
		char *name;
		elog_sp_cat(&name, elog_set_path(NULL), "/", &fileHandle[8], NULL);
		elog_gui_io_open(name, NULL);
		free(name);
	}
	else if (fileHandle[0] == 's' &&
				fileHandle[1] == 'e' &&
				fileHandle[2] == 'a' &&
				fileHandle[3] == 'r' &&
				fileHandle[4] == 'c' &&
				fileHandle[5] == 'h' &&
				fileHandle[6] == ':')
	{

		char **token = elog_sp_breakToArr(fileHandle, '/');
		elog_gui_al_searchText(token[1]);

		if (elog_srch_status() == ELOG_SRCH_STAT_GO) //better make sure it's done searching
			traverSearch(elog_set_get_str("path"), token[1], elog_gui_io_search);
		elog_gui_al_page(ELOG_GUI_AL_PAGE_SRCH);
		elog_sp_ArrFree(token);
	}
	else if (fileHandle[0] == 'h' &&
				fileHandle[1] == 't' &&
				fileHandle[2] == 't' &&
				fileHandle[3] == 'p' &&
				fileHandle[4] == ':')
	{
	  const char *browser = elog_set_get_str("BROWSER");
	  if (!browser)
	    browser = "firefox";
		char *cmd;
		elog_sp_cat(&cmd, browser, " ", &(fileHandle[7]), NULL);
		printf("Command:%s\n", cmd);
		system(cmd);
		free(cmd);
	}
	 
}
 void elog_gui_previewPane_set(struct elog_xml_doc *meta)
{
	elog_gui_al_mood(-2);
	elog_gui_al_weather(meta->weather);
	elog_gui_al_mood(meta->mood);
	 //elog_gui_al_setImage(meta->mood, meta->weather);
	 //^^^ gets loaded by the callbacks.
	elog_gui_al_title(meta->subject);
	 
	char *day, *month, *year;
	day = elog_sp_shortToString(meta->day);
	month = (char *)elog_mnth_str(meta->month);
	
	year = elog_sp_shortToString(meta->year);
	char *str;
	elog_sp_cat(&str, "The ", day, elog_mnth_day(meta->day), " of ", month, ", ", year, NULL);
	elog_gui_al_creationDate(str);
	free(str);
	free(day);
	free(year);
	 //dontFree(month);


	 
	elog_gui_al_lastEdit(meta->last_edit);
	if (meta->links)
	{
		int c;
		for (c=0; meta->links[c] != NULL; ++c)
			elog_gui_al_addLink(meta->links[c]);
	}
}
 struct elog_xml_doc *elog_gui_getMeta()
{
	struct elog_xml_doc *meta;
			
	elog_set_currentFile(NULL, &meta);

	if (meta == NULL)
		meta = elog_xml_doc_new();
	
	if (meta->subject) free(meta->subject);
	meta->subject = elog_gui_al_title(NULL);
	meta->weather = elog_gui_al_weather(-1);
	meta->mood = elog_gui_al_mood(-1);

	if (meta->last_edit) free(meta->last_edit);
	meta->last_edit = elog_gui_al_lastEdit(NULL);
	if (meta->created) free(meta->created);
	meta->created = elog_gui_al_creationDate(NULL);
	//meta->links = elog_gui_al_getLinks(); //we simply keep up with links
	return meta;
}
 int elog_gui_io_save()
{
  struct elog_xml_doc *current = elog_gui_getMeta();
  unsigned int len;
  unsigned char *txt = elog_sp_toUnsignedChar(elog_gui_al_text(NULL), &len);
  current->text = elog_sp_toChar(txt, len);
  
  if (txt[0] == '\0')
    return 1;
  
  
  /*Calling plugins*/
  struct elog_plgn_data_io *plgn = malloc(sizeof *plgn);
  plgn->doc = current;
  plgn->xml = NULL;
  elog_plgn_call_all("___save", plgn);
  free(plgn);
  /*end plugins*/
  
  const char *journ = elog_journ_in_current(current->fileName);
  if (journ)
    {
      char *msg = "You need to switch journals to save the currently opened file.\nWould you like to do so?  If you click yes, you will switch to a different journal and save it.\nIf you click no, you will stay here but the file will remain unsaved!";
      int res = elog_wrn_ask(msg, ELOG_WRN_ASK_YESNO);
      if (res)
	{
	  if (elog_journ_load(journ))
	    {
	      elog_err_print("Failed to load journal!\n");
	      return 3;
	    }
	}
      else
	return 2;
    }

  
  if (elog_set_get_str("encryption_method")[0] == 'A')
    encryptText(txt, len);
  if (current->file_info->encType != NULL)
    free(current->file_info->encType);
  elog_sp_cat(&(current->file_info->encType), elog_set_get_str("encryption_method"), NULL);
  
  
  elog_sp_cat(&(current->last_edit), elog_io_date(), NULL);
  
  
  elog_xml_save(current->fileName, current, txt, len);
  
  elog_gui_io_highlight_do();
  
  free(txt);
  return 0;
}
void elog_gui_io_setSyncNeeded()	{	sync_needed = 1;	}

void elog_gui_io_view_set_result_mode(int mode)
{
	_cal_mode = mode;
}
void elog_gui_io_markCalendar()
{
	switch (_cal_mode)
	{
		case 0:
		{
			elog_gui_io_view_dir_results();
			break;
		}
		case 1:
		{
			elog_gui_io_view_srch_results();
			break;
		}
	}
}
void elog_gui_io_view_dir_results()
{
	elog_gui_al_clearMarks();



	struct cal_date *date = elog_gui_al_calendarDate(NULL);

	char *year; char *month; 
  
  
	year = elog_sp_shortToString(date->year);
	month = elog_sp_shortToString(date->month);
  
	const char *path = elog_set_path(NULL);

	char *file;
	elog_sp_cat(&file, path, "/", year, "/", month, NULL);
  
	
	free(year); free(month);  
	
	
	char **list = elog_io_dirContents(file);
	free(file);
	
	int c;
	for (c=0; list[c] != NULL; ++c)
	{
		int day = elog_sp_stringToShort(list[c]);
		elog_gui_al_markDate(day);
	
		free(list[c]);
	}
	free(list);
	free(date);
}
void elog_gui_io_addLink(struct elog_xml_link *lnk)
{
	struct elog_xml_doc *current;
	elog_set_currentFile(NULL, &current);
	
	
	struct elog_xml_link **nue;
	
	int size=0;
	if (current->links != NULL)
		for (size=0; current->links[size] != NULL; ++size) ; //size finder
		
	nue = malloc ((sizeof *nue) * (size+2));
	int c;
	for (c=0; c < size; ++c)
		nue[c] = current->links[c];
	nue[size] = lnk;
	nue[size+1] = NULL;
	free(current->links);
	current->links = nue;
	
	elog_set_currentFile(current->fileName, &current);
	//elog_gui_io_addUndoActionPtr(ELOG_GUI_IO_ACTION_LINK, lnk, 0);
}
int elog_gui_io_checkRange(int loc, struct elog_xml_link **lnk)
{
	*lnk = NULL;
	struct elog_xml_doc *current;
	elog_set_currentFile(NULL, &current);
	if (!current)
		return 0;
	if (current->links == NULL)
		return 0;
	int c;
	for (c = 0; current->links[c] != NULL; ++c)
	{
		if (loc < current->links[c]->start && loc > current->links[c]->end)
		{
			*lnk = current->links[c];
			return 1;
		}
	}
	return 0;
}
void elog_gui_io_updateTags(int start, int len)
{
	struct elog_xml_doc *current;
	elog_set_currentFile(NULL, &current);
	if (current->links == NULL)
		return;
	int c;
	for (c = 0; current->links[c] != NULL; ++c)
	{
	
		if (current->links[c]->start > start)
		{
			current->links[c]->start += len;
			current->links[c]->end += len;
		}
	}
	
}
void elog_gui_io_removeLink(int loc)
{
	struct elog_xml_doc *current;
	elog_set_currentFile(NULL, &current);
	if (current->links == NULL)
		return;
	int c;
	for (c = 0; current->links[c] != NULL; ++c)
	{
		if (loc <= current->links[c]->start && loc >= current->links[c]->end)
		{
			char *title = elog_sp_shortToString(current->links[c]->num);

			elog_gui_al_removeLink(title);

			free(title);
			
			//don't free link, undo needs it!
			int j=c;
			for (; current->links[j] != NULL; ++j)
				current->links[j] = current->links[j+1];
			break;
		}
	}
}
struct cal_date *elog_gui_io_getDate(const char *fileName)
{

	char **token = elog_sp_breakToArr(fileName, '/');

	if (token == NULL)
		return NULL; //this should never happen.
	int c;
	for (c=0; token[c] != NULL; ++c) ; //intentional
		
	struct cal_date *date = malloc(sizeof *date);
		
	date->month = elog_sp_stringToShort(token[c-2]);
	date->year = elog_sp_stringToShort(token[c-3]);
	date -> day = elog_sp_stringToShort(token[c-1]);


	elog_sp_ArrFree(token);
	return date;
}
void elog_gui_io_dispLocation(const char *fileName)
{
	char *realDay; //taking off the /day at the end, this gives
	//compatibility with full filenames.
	char *t;
	elog_sp_cat(&t, fileName, NULL);
	*(strrchr(t, '/')) = '\0';

	elog_sp_cat(&realDay, t, NULL);
	free(t);
	
	struct cal_date *date = elog_gui_io_getDate(realDay);

	elog_gui_al_calendarDate(date);

	free(date);
	elog_gui_io_dispDay(realDay);
	free(realDay);
}

void elog_gui_io_dispDay(const char *day)
{
  if (day == NULL)
    day = _day;
  else
    {
      if (_day != NULL)
	free(_day);
      elog_sp_cat(&_day, day, NULL); //storing current day
    }
  
  if (day == NULL)
    return; //bail no data to use!
  
  
  elog_gui_al_clearDay();
  
  char **content = elog_io_dirContents(day);
  
  if (content == NULL)
    {
      elog_err_print_console("Warning, day does not exist\n");
      return;
    }
	

  int c;
  for (c=0; content[c] != NULL; ++c)
    {
      if (_cal_mode)
	{ //do this if we're worried about search results.
	  char **list = elog_sp_breakToArr(day, '/');
	  int i;
	  for (i=0; list[i]; ++i) ;
	  int year, month, day;
	  year = elog_sp_stringToShort(list[i-3]);
	  month = elog_sp_stringToShort(list[i-2]);
	  day = elog_sp_stringToShort(list[i-1]);
	  content[c][strlen(content[c])-4] = '\0';
	  int n = elog_sp_stringToShort(content[c]);

	  content[c][strlen(content[c])] = '.';

	  //.../year/month/day/NULL
	  //    i-3  i-2   i-1  i
	  elog_sp_ArrFree(list);
	  if (!(elog_gui_io_view_in_srch_results(year, month, day, n)))
	    continue; //skip this one, it's NOT there.
	}
      

      char *path;
      elog_sp_cat(&path, day, "/", content[c], NULL); //full fileName
      struct elog_xml_doc *file = elog_xml_open(path, 0);
      free(path);

      //add day!
      if (file)
	{
	  if (file->handle)
	    {
	      elog_io_close(file->handle);
	      elog_gui_al_addItemToDay(file->subject, file->fileName, file->mood);
	    }
	  elog_xml_doc_free(file);

	}
      free(content[c]);
    }
  char *name = elog_sp_shortToString(++c);
  char *path;
  elog_sp_cat(&path, day, "/", name, ".dry", NULL);
  elog_gui_al_addItemToDay("Add A New Entry", path, -1);
  free(name);
  free(path);
  free(content);
}
void elog_gui_io_newEntry(const char *day)
{
  
	char **content = elog_io_dirContents(day);
	if (content == NULL)
	{
		char *path;
		elog_sp_cat(&path, day, "/", "1.dry", NULL);
		elog_gui_io_open(path, NULL);
		free(path);		
		return;
	}
	int c;
	for (c=0; content[c] != NULL; ++c) ; //intentional
	 
	char *name = elog_sp_shortToString(++c);
	char *path;
	elog_sp_cat(&path, day, "/", name, ".dry", NULL);
	elog_gui_io_open(path, NULL);
	free(name);
	free(path);
	free(content);
	
}

struct _gui_io_results
{
	int val;
	struct _gui_io_results *next;
	struct _gui_io_results *child;
};
struct _gui_io_results *_grandDaddy = NULL;

int elog_gui_io_view_in_srch_results(int year, int month, int day, int n)
{
  struct _gui_io_results *p = _grandDaddy;
  while (p)
    {
      if (p->val == year)
	{
	  p=p->child;
	  while (p)
	    {
	      if (p->val == month)
		{
		  p=p->child;
		  while (p)
		    {
		      if (p->val == day)
			{
			  p=p->child;
			  while (p)
			    {
			      if (p->val == n)
				  return 1;
			      p=p->next;
			    }
			  return 0;
			}
		      p=p->next;
		    }
		  return 0;
		}
	      p=p->next;
	    }
	  return 0;
	}
      p=p->next;
    }
  return 0;
}

void elog_gui_io_view_srch_results()
{
  elog_gui_al_clearMarks();
  struct cal_date *date = elog_gui_al_calendarDate(NULL);
  int year = date->year;
  int month = date->month;
  free(date);
  struct _gui_io_results *p = _grandDaddy;
  while (p)
    {
      if (p->val == year)
	{
	  p = p->child;
	  while (p)
	    {
	      if (p->val == month)
		{
		  p=p->child;
		  while (p)
		    {
		      elog_gui_al_markDate(p->val);
		      p=p->next;
		    }
		  break;
		}
	      p=p->next;
	    }
	  break;
	}
      p=p->next;
    }
}


struct _gui_io_results *_gui_io_result_new()
{
	struct _gui_io_results *ret = malloc(sizeof *ret);
	ret->next = NULL;
	ret->child = NULL;
	ret->val = 0;
	return ret;
}
void elog_gui_io_view_add_result(int year, int month, int day, int n)
{
  struct _gui_io_results *p = _grandDaddy;
  while (p)
    {
      if (p->val == year)
	{
	  p = p->child;
	  while (p)
	    {
	      if (p->val == month)
		{
		  p = p->child;
		  while (p)
		    {
		      if (p->val == day)
			{
			  p=p->child;
			  struct _gui_io_results *q = p->next;
			  p->next = _gui_io_result_new();
			  p->next->next = q;
			  p->next->val = n;
			  return;
			}
		      if (p->next)
			p=p->next;
		      else
			{
			  p->next = _gui_io_result_new();
			  p->next->val = day;
			  p->next->child = _gui_io_result_new();
			  p->next->child->val = n;
			  return;
			}
		    }
		}
	      if (p->next)
		p=p->next;
	      else
		{
		  p->next = _gui_io_result_new();
		  p->next->val = month;
		  p->next->child = _gui_io_result_new();
		  p->next->child->val = day;
		  p->next->child->child = _gui_io_result_new();
		  p->next->child->child->val = n;
		  return;
		}
	    }
	}
      if (p->next)
	p=p->next;
      else
	{
	  p->next = _gui_io_result_new();
	  p->next->val = year;
	  p->next->child = _gui_io_result_new();
	  p->next->child->val = month;
	  p->next->child->child = _gui_io_result_new();
	  p->next->child->child->val = day;
	  p->next->child->child->child = _gui_io_result_new();
	  p->next->child->child->child->val = n;
	  return;
	}
	
    }
  if (!p)
    {
      p = _gui_io_result_new();
      p->val = year;
      p->child = _gui_io_result_new();
      p->child->val = month;
      p->child->child = _gui_io_result_new();
      p->child->child->val = day;
      p->child->child->child = _gui_io_result_new();
      p->child->child->child->val = n;
      _grandDaddy = p;
    }
}

void _gui_io_result_free(struct _gui_io_results *res)
{
	
	if (res->next)
		_gui_io_result_free(res->next);
	if (res->child)
		_gui_io_result_free(res->child);

	free(res);
}
void elog_gui_io_view_clear_results()
{
	if (_grandDaddy)
		_gui_io_result_free(_grandDaddy);
	_grandDaddy = NULL;
}
void elog_gui_io_view_next_result()
{
	if (elog_gui_io_res_list)
	{
		elog_gui_io_res_cur+=2;
		if (elog_gui_io_res_cur >= elog_gui_io_res_list_len)
			elog_gui_io_res_cur-=2;
		elog_gui_al_jump_to(elog_gui_io_res_list[elog_gui_io_res_cur]);
	}
}
void elog_gui_io_view_prev_result()
{
	if (elog_gui_io_res_list)
	{
		elog_gui_io_res_cur-=2;
		if (elog_gui_io_res_cur < 0)
			elog_gui_io_res_cur = 0;
		elog_gui_al_jump_to(elog_gui_io_res_list[elog_gui_io_res_cur]);
	}
}




void elog_gui_io_open_manual()
{
  const char *browser = elog_set_get_str("BROWSER");
  if (!browser)
    browser = "gnome-open";
  char *call;
  elog_sp_cat(&call, browser, " ", DATADIR, "/ejourn/doc/index.html &", NULL);
  system(call);
  free(call);
}
